package cn.lingyangwl.agile.infra;

import cn.lingyangwl.agile.infra.common.ScanScene;
import cn.lingyangwl.agile.infra.module.datamanage.db.*;
import cn.lingyangwl.agile.infra.module.file.constants.FileCons;
import cn.lingyangwl.agile.infra.module.file.model.rqrs.FileRecordResp;
import cn.lingyangwl.agile.infra.module.file.model.rqrs.MediaMaterialResp;
import cn.lingyangwl.agile.infra.module.group.model.rqrs.*;
import cn.lingyangwl.agile.infra.module.misc.*;
import cn.lingyangwl.agile.model.enums.DataGroupBizTypeEnum;
import cn.lingyangwl.framework.core.response.Resp;
import cn.lingyangwl.framework.core.response.RetOps;
import cn.lingyangwl.framework.tool.core.UrlUtils;
import cn.lingyangwl.framework.tool.core.exception.BizException;
import com.alibaba.cloud.nacos.NacosServiceAutoConfiguration;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.cloud.openfeign.FeignAutoConfiguration;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;

/**
 * @author shenguangyang
 */
@Lazy
@Slf4j
@Service
@ConditionalOnClass({FeignAutoConfiguration.class, NacosServiceAutoConfiguration.class})
public class InfraCloudApiImpl implements InfraApi {
    @Resource
    private InfraRemote infraRemote;

    private static final List<String> internalNetIps = Arrays.asList(
        "127.0.0.1", "localhost"
    );

    @Override
    public MediaMaterialResp getMediaMaterial(Long id) {
        Resp<MediaMaterialResp> resp = infraRemote.getMediaMaterial(id);
        RetOps.of(resp).assertSuccess(e -> new BizException(e.getCode(), e.getMsg()));
        return resp.getData();
    }

    @Override
    public Long saveDataGroup(DataGroupSaveReq req) {
        Resp<Long> resp = infraRemote.saveDataGroup(req);
        RetOps.of(resp).assertSuccess(e -> new BizException(e.getCode(), e.getMsg()));
        return resp.getData();
    }

    @Override
    public List<DataGroupDto> listChildrenDataGroup(Long parentId) {
        Resp<List<DataGroupDto>> resp = infraRemote.listChildrenDataGroup(parentId);
        RetOps.of(resp).assertSuccess(e -> new BizException(e.getCode(), e.getMsg()));
        return resp.getData();
    }

    @Override
    public List<DataGroupDto> listDataGroup(DataGroupQuery req) {
        Resp<List<DataGroupDto>> resp = infraRemote.listDataGroup(req);
        RetOps.of(resp).assertSuccess(e -> new BizException(e.getCode(), e.getMsg()));
        return resp.getData();
    }

    @Override
    public boolean updateDataGroup(DataGroupUpdateReq req) {
        Resp<Boolean> resp = infraRemote.updateDataGroup(req);
        RetOps.of(resp).assertSuccess(e -> new BizException(e.getCode(), e.getMsg()));
        return resp.getData();
    }

    @Override
    public DataGroupDto getDataGroup(Long id) {
        Resp<DataGroupDto> resp = infraRemote.getDataGroup(id);
        RetOps.of(resp).assertSuccess(e -> new BizException(e.getCode(), e.getMsg()));
        return resp.getData();
    }

    @Override
    public boolean deleteDataGroup(DataGroupBizTypeEnum type, Long id) {
        Resp<Boolean> resp = infraRemote.deleteDataGroup(type.getType(), id);
        RetOps.of(resp).assertSuccess(e -> new BizException(e.getCode(), e.getMsg()));
        return resp.getData();
    }

    @Override
    public boolean batchDeleteDataGroup(DataGroupDeleteReq req) {
        Resp<Boolean> resp = infraRemote.batchDeleteDataGroup(req.getBizType(), req.getIds());
        RetOps.of(resp).assertSuccess(e -> new BizException(e.getCode(), e.getMsg()));
        return resp.getData();
    }

    @Override
    public String getFileIntranetUrl(String filePath) {
        filePath = filePath.replace(FileCons.UPLOAD_BASE_URL, "");
        Resp<String> resp = infraRemote.getFileIntranetUrl();
        RetOps.of(resp).assertSuccess(e -> new BizException(e.getCode(), e.getMsg()));
        String url = UrlUtils.removeRepeatSlashOfUrl(resp.getData() + "/" + filePath);
        log.debug("intranet file url: {}", url);
        return url;
    }

    @Override
    public FileRecordResp getFileRecordByPath(String path, boolean isIntranet) {
        Resp<FileRecordResp> resp = infraRemote.getFileRecordByPath(path, isIntranet);
        RetOps.of(resp).assertSuccess(e -> new BizException(e.getCode(), e.getMsg()));
        return resp.getData();
    }

    @Override
    public void deleteFileRecordByPath(String path) {
        Resp<?> resp = infraRemote.deleteFileRecordByPath(path);
        RetOps.of(resp).assertSuccess(e -> new BizException(e.getCode(), e.getMsg()));
    }

    @Override
    public String getMpQrcode(ScanScene req) {
        Resp<String> resp = infraRemote.getMpQrcode(req);
        RetOps.of(resp).assertSuccess(e -> new BizException(e.getCode(), e.getMsg()));
        return resp.getData();
    }

    @Override
    public Short getIdGenNextWorkId() {
        Resp<Short> resp = infraRemote.getIdGenNextWorkId();
        RetOps.of(resp).assertSuccess(e -> new BizException(e.getCode(), e.getMsg()));
        return resp.getData();
    }

    @Override
    public void refreshIdGenWorkId(Short workId) {
        Resp<Boolean> resp = infraRemote.refreshIdGenWorkId(workId);
        RetOps.of(resp).assertSuccess(e -> new BizException(e.getCode(), e.getMsg()));
    }

    @Override
    public List<SQLContext> listSqlContext(Long datasourceId, List<String> tableNames) {
        Resp<List<SQLContext>> resp = infraRemote.listSqlContext(datasourceId, tableNames);
        RetOps.of(resp).assertSuccess(e -> new BizException(e.getCode(), e.getMsg()));
        return resp.getData();
    }

    @Override
    public Optional<Ip2RegionDto> ip2Region(String ip) {
        if (internalNetIps.contains(ip)) {
            Ip2RegionDto dto = new Ip2RegionDto();
            dto.setCity("内网IP");
            return Optional.of(dto);
        }
        Resp<Ip2RegionDto> resp = infraRemote.ip2Region(ip);
        RetOps.of(resp).assertSuccess(e -> new BizException(e.getCode(), e.getMsg()));
        return Optional.ofNullable(resp.getData());
    }
}
